import 'dart:async';
import 'dart:math';

import 'package:flutter/cupertino.dart';

class BubbleWidget extends StatefulWidget {
  final int bubbleCout;
  BubbleWidget({this.bubbleCout = 20});
  @override
  _BubbleWidgetState createState() => _BubbleWidgetState();
}

class _BubbleWidgetState extends State<BubbleWidget>
    with TickerProviderStateMixin {
  //创建的气泡保存集合
  List<BobbleBean> _list = [];

  //随机数据
  Random _random = new Random(DateTime.now().microsecondsSinceEpoch);

  //气泡的最大半径
  double maxRadius = 50;

  //气泡动画的最大速度
  double maxSpeed = 0.7;

  //气泡计算使用的最大弧度（360度）
  double maxTheta = 2.0 * pi;

  //动画控制器
  AnimationController _animationController;

  //流控制器
  StreamController<double> _streamController = new StreamController();

  AnimationController _fadeAnimationController;

  @override
  void initState() {
    super.initState();
    for (var i = 0; i < widget.bubbleCout; i++) {
      BobbleBean particle = new BobbleBean();
      particle.color = getRandomColor(_random);
      particle.speed = _random.nextDouble() * maxSpeed;
      particle.theta = _random.nextDouble() * maxTheta;
      particle.radius = _random.nextDouble() * maxRadius;
      _list.add(particle);
    }
    _animationController = new AnimationController(
        vsync: this, duration: Duration(milliseconds: 1000));
    _animationController.addListener(() {
      _streamController.add(0.0);
    });

    _fadeAnimationController = new AnimationController(
        vsync: this, duration: Duration(milliseconds: 500));

    _fadeAnimationController.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        _animationController.repeat();
      }
    });
    _fadeAnimationController.forward();
  }

  @override
  void dispose() {
    _streamController.close();
    _animationController.dispose();
    _fadeAnimationController.dispose();
    super.dispose();
  }

  Color getRandomColor(Random random) {
    var radom = new Random().nextInt(150);
    return Color.fromARGB(radom, 255, 255, 255);
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<double>(
      stream: _streamController.stream,
      builder: (BuildContext context, AsyncSnapshot<double> snapshot) {
        //自定义画板
        return CustomPaint(
          //自定义画布
          painter: CustomMyPainter(
            list: _list,
            random: _random,
          ),
          child: Container(
            height: MediaQuery.of(context).size.height,
          ),
        );
      },
    );
  }
}

class CustomMyPainter extends CustomPainter {
  Paint _paint = Paint();
  List<BobbleBean> list;
  Random random;

  CustomMyPainter({this.list, this.random});

  @override
  void paint(Canvas canvas, Size size) {
    list.forEach((element) {
      if (element.postion == null) {
        element.postion = Offset(random.nextDouble() * size.width,
            random.nextDouble() * size.height);
      }
      double scrW = size.width - element.radius;
      double scrH = size.height - element.radius;
      if (element.postion.dx < element.radius) {
        if (element.theta > pi && element.theta < pi + pi / 2) {
          element.theta = pi * 3 - element.theta;
        }

        if (element.theta > pi / 2 && element.theta < pi) {
          element.theta = pi - element.theta;
        }
      }

      if (element.postion.dx > scrW) {
        if (element.theta > pi + pi / 2 && element.theta < 2 * pi) {
          element.theta = 3 * pi - element.theta;
        }
        if (element.theta < pi / 2) {
          element.theta = pi - element.theta;
        }
      }

      if (element.postion.dy > scrH) {
        if (element.theta > pi / 2) {
          element.theta = pi * 2 - element.theta;
        }
        if (element.theta < pi / 2) {
          element.theta = 2 * pi - element.theta;
        }
      }

      if (element.postion.dy < element.radius) {
        if (element.theta > pi && element.theta < pi + pi / 2) {
          element.theta = pi * 2 - element.theta;
        }
        if (element.theta > pi + pi / 2 && element.theta < 2 * pi) {
          element.theta = pi * 2 - element.theta;
        }
      }

      var velocity = calculateXY(element.speed, element.theta);
      var dx = element.postion.dx + velocity.dx;
      var dy = element.postion.dy + velocity.dy;
      element.postion = Offset(dx, dy);
    });

    list.forEach((element) {
      _paint.color = element.color;
      canvas.drawCircle(element.postion, element.radius, _paint);
    });
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }

  Offset calculateXY(double speed, double theta) {
    return Offset(speed * cos(theta), speed * sin(theta));
  }
}

class BobbleBean {
  Offset postion;
  Color color;
  double speed;
  double theta;
  double radius;
}
